package com.gorilla.aspect.impl;

import com.gorilla.aspect.annotation.SubmitLock;
import com.gorilla.aspect.exception.GorillaException;
import com.gorilla.aspect.util.KeyResolverUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * The Idempotent Aspect
 *
 * @author eshop
 */
@Aspect
@Slf4j
public class SubmitLockAspect {



	@Autowired
	private StringRedisTemplate redisTemplate;


	@Pointcut("@annotation(com.gorilla.aspect.annotation.SubmitLock)")
	public void pointCut() {
	}

	@SneakyThrows
	@Before("pointCut()")
	public void noReSubmit(JoinPoint joinPoint) {
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		if (!method.isAnnotationPresent(SubmitLock.class)) {
			return;
		}
		SubmitLock submitLock = method.getAnnotation(SubmitLock.class);

		String val =submitLock.value();
		String key;
		if (StringUtils.isEmpty(submitLock.key())) {
			key = val;
		} else {
			key = KeyResolverUtil.resolver(submitLock.key(), joinPoint);

			if(!StringUtils.isEmpty(val)){
				key = val+":"+key;
			}
		}

		long expireTime = submitLock.expireTime();
		String info = submitLock.info();
		TimeUnit timeUnit = submitLock.timeUnit();
		String value = LocalDateTime.now().toString().replace("T", " ");

		boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, timeUnit);
		if(!result){
			log.warn("SubmitLock key={}",key);
			throw new GorillaException(info);
		}


	}



}
